/* global angular,ionic */
(function (angular, ionic) {
    'use strict';

    angular.module('ionic.scroll.sh', ['ionic'])
        .directive('scrollSh', ['$document', '$timeout', '$rootScope', '$ionicScrollDelegate', '$window', function ($document, $timeout, $rootScope, $ionicScrollDelegate, $window) {
            var TRANSITION_DELAY = 400;
            var defaultDelay = TRANSITION_DELAY * 2;
            var defaultDuration = TRANSITION_DELAY + 'ms';
            var scaleHeaderElements = ionic.Platform.isAndroid() ? false : true;

            function getParentWithAttr(e, attrName, attrValue, depth) {
                var attr;

                depth = depth || 10;
                while (e.parentNode && depth--) {
                    attr = e.parentNode.getAttribute(attrName);
                    if (attr && attr === attrValue) {
                        return e.parentNode;
                    }
                    e = e.parentNode;
                }
                return null;
            }

            return {
                restrict: 'A',
                link: function ($scope, $element, $attr) {
                    var isNavBarTransitioning = true;
                    var body = $document[0].body;
                    var scrollDelegate = $attr.delegateHandle ? $ionicScrollDelegate.$getByHandle($attr.delegateHandle) : $ionicScrollDelegate;
                    var scrollView = scrollDelegate.getScrollView();

                    //coordinates
                    var y, prevY, prevScrollTop;
                    //headers
                    var cachedHeader, activeHeader, headerHeight, contentTop;
                    //subheader
                    var subHeader, subHeaderHeight;
                    //tabs
                    var tabs, tabsHeight, hasTabsTop = false, hasTabsBottom = false;
                    var footerMenu;
                    //y position that will indicate where specific elements should start and end their transition.
                    var headerStart = 0;
                    var tabsStart = 0;
                    var subheaderStart = 0;
                    var defaultEnd, headerEnd, tabsEnd, subheaderEnd;

                    /**
                     * translates an element along the y axis by the supplied value.  if duration is passed in,
                     * a transition duration is set
                     * @param element
                     * @param y
                     * @param duration
                     */
                    function translateY(element, y, duration) {
                        if (duration && !element.style[ionic.CSS.TRANSITION_DURATION]) {
                            element.style[ionic.CSS.TRANSITION_DURATION] = duration;
                            $timeout(function () {
                                element.style[ionic.CSS.TRANSITION_DURATION] = '';
                            }, defaultDelay, false);
                        }
                        element.style[ionic.CSS.TRANSFORM] = 'translate3d(0, ' + (-y) + 'px, 0)';
                    }

                    /**
                     * Initializes y and scroll variables
                     */
                    function initCoordinates() {
                        y = 0;
                        prevY = 0;
                        prevScrollTop = 0;
                    }

                    /**
                     * Initializes headers, tabs, and subheaders, and determines how they will transition on scroll
                     */
                    function init() {
                        var activeView;

                        cachedHeader = body.querySelector('[nav-bar="cached"] .bar-header');
                        activeHeader = body.querySelector('[nav-bar="active"] .bar-header');

                        if (!activeHeader) {
                            return;
                        }

                        headerHeight = activeHeader.offsetHeight;
                        contentTop = headerHeight;

                        //since some people can have nested tabs, get the last tabs
                        tabs = body.querySelectorAll('.tabs');
                        tabs = tabs[tabs.length - 1];
                        if (tabs) {
                            tabsHeight = tabs.offsetHeight;
                            if (tabs.parentNode.classList.contains('tabs-top')) {
                                hasTabsTop = true;
                                contentTop += tabsHeight;
                            } else if (tabs.parentNode.classList.contains('tabs-bottom')) {
                                hasTabsBottom = true;
                            }
                        }

                        footerMenu = body.querySelectorAll('.footer-menu');
                        footerMenu = footerMenu[footerMenu.length - 1];
                        //subheader
                        //since subheader is going to be nested in the active view, get the closest active view from $element and
                        activeView = getParentWithAttr($element[0], 'nav-view', 'active');
                        subHeader = activeView && activeView.querySelector('.bar-subheader');
                        if (subHeader) {
                            subHeaderHeight = subHeader.offsetHeight;
                            contentTop += subHeaderHeight;
                        }

                        //set default end for header/tabs elements to scroll out of the scroll view and set elements end to default
                        defaultEnd = contentTop * 2;
                        headerEnd = tabsEnd = subheaderEnd = defaultEnd;

                        //if tabs or subheader aren't available, set height to 0
                        tabsHeight = tabsHeight || 0;
                        subHeaderHeight = subHeaderHeight || 0;

                        switch ($attr.scrollSh) {
                            case 'header':
                                subheaderEnd = headerHeight;
                                tabsEnd = hasTabsTop ? headerHeight : 0;
                                break;
                            case 'header-tabs':
                                headerStart = hasTabsTop ? tabsHeight : 0;
                                subheaderEnd = hasTabsTop ? headerHeight + tabsHeight : headerHeight;
                                break;
                            case 'tabs-subheader':
                                headerEnd = 0;
                                headerStart = hasTabsTop ? contentTop - headerHeight : subHeaderHeight;
                                tabsStart = hasTabsTop ? subHeaderHeight : 0;
                                break;
                            case 'tabs':
                                headerEnd = 0;
                                subheaderEnd = hasTabsTop ? tabsHeight : 0;
                                break;
                            case 'subheader':
                                headerEnd = 0;
                                tabsEnd = 0;
                                break;
                            case 'header-subheader':
                                tabsEnd = hasTabsTop ? headerHeight : 0;
                                break;
                            case 'subheader-header':
                                headerStart = subHeaderHeight;
                                tabsStart = hasTabsTop ? subHeaderHeight : 0;
                                tabsEnd = hasTabsTop ? headerHeight : 0;
                                break;
                            //defaults to header-tabs-subheader
                            default:
                                headerStart = hasTabsTop ? contentTop - headerHeight : subHeaderHeight;
                                tabsStart = hasTabsTop ? subHeaderHeight : 0;
                        }
                    }

                    /**
                     * Translates active and cached headers, and animates active children
                     * @param y
                     * @param duration
                     */
                    //function translateHeaders(y, duration) {
                    //    var fadeAmt = Math.max(0, 1 - (y / headerHeight));
                    //
                    //    //translate active header
                    //    if (activeHeader) {
                    //        translateY(activeHeader, y, duration);
                    //        angular.forEach(activeHeader.children, function (child) {
                    //            child.style.opacity = fadeAmt;
                    //            if (scaleHeaderElements) {
                    //                child.style[ionic.CSS.TRANSFORM] = 'scale(' + fadeAmt + ',' + fadeAmt + ')';
                    //            }
                    //        });
                    //    }
                    //
                    //    //translate cached header
                    //    if (cachedHeader) {
                    //        translateY(cachedHeader, y, duration);
                    //    }
                    //}

                    /**
                     * Translates header, tabs, subheader elements and resets content top and/or bottom
                     * When the active view leaves, we need sync functionality to reset headers and clear
                     * @param y
                     * @param duration
                     */
                    function translateElementsSync(y, duration) {
                        //var contentStyle = $element[0].style;
                        //tabs

                        if (tabs) {
                            //console.log(tabsHeight)
                            if (y) {
                                //translateY(tabs, -tabsHeight, duration);
                                translateY(tabs, -49, duration);
                                if (footerMenu) {
                                    translateY(footerMenu, -49, duration);
                                }
                                //contentStyle.bottom = '0px';

                            } else {
                                translateY(tabs, 0, duration);
                                if (footerMenu) {
                                    translateY(footerMenu, 0, duration);
                                }
                                //contentStyle.bottom = tabsHeight+'px';

                            }
                        }

                        //headers
                        //translateHeaders(Math.min(headerEnd, headerY), duration);

                        //readjust top of ion-content
                        //contentStyle.top = Math.max(0, contentTop - y) + 'px';
                    }

                    /**
                     * Translates header, tabs, subheader elements and resets content top and/or bottom
                     * Wraps translate functionality in an animation frame request
                     * @param y
                     * @param duration
                     */
                    function translateElements(y, duration) {
                        ionic.requestAnimationFrame(function () {
                            translateElementsSync(y, duration);
                        });
                    }

                    //Need to reinitialize the values on refreshComplete or things will get out of wack
                    $scope.$on('scroll.refreshComplete', function () {
                        initCoordinates();
                    });

                    /**
                     * Before the active view leaves, reset elements, and reset the scroll container
                     */
                    $scope.$parent.$on('$ionicView.beforeLeave', function () {
                        isNavBarTransitioning = true;
                        translateElementsSync(0);
                        activeHeader = null;
                        cachedHeader = null;
                    });

                    /**
                     * Scroll to the top when entering to reset then scrollView scrollTop. (prevents jumping)
                     */
                    $scope.$parent.$on('$ionicView.beforeEnter', function () {
                        if (scrollView) {
                            scrollView.scrollTo(0, 0);
                        }
                    });

                    /**
                     * Ionic sets the active/cached nav-bar AFTER the afterEnter event is called, so we need to set a small
                     * timeout to let the nav-bar logic run.
                     */
                    $scope.$parent.$on('$ionicView.afterEnter', function () {
                        initCoordinates();
                        $timeout(function () {
                            init();
                            isNavBarTransitioning = false;
                        }, 20, false);
                    });
                    /**
                     * Called onScroll.  computes coordinates based on scroll position and translates accordingly
                     */
                    var isWebapp = Boolean($window.navigator.standalone);
                    if (!isWebapp) {
                        $element.bind('scroll', function (e) {
                            if (isNavBarTransitioning) {
                                return;
                            }
                            //support for jQuery event as well
                            //e = e.originalEvent || e;
                            //console.log($ionicScrollDelegate.getScrollPosition().top)

                            var duration = 0;
                            //var scrollTop = e.detail.scrollTop;
                            if (e.detail && e.detail.scrollTop) {
                                var scrollTop = e.detail.scrollTop;
                            } else {
                                var scrollTop = $ionicScrollDelegate.getScrollPosition().top;
                            }
                            if (scrollTop > prevScrollTop && scrollTop > 100) {
                                y = true;
                            } else {
                                y = false;
                            }
                            $timeout(function () {
                                prevScrollTop = scrollTop;
                            }, 30);
                            translateElements(y, duration);
                        });
                    }
                }
            }
        }]);
})(angular, ionic);
